package com.fuhailiu.opengl.utils;

import android.opengl.Matrix;

/**
 * 存储矩阵状态的类
 */

public class MatrixUtil {

	private static final String TAG = MatrixUtil.class.getSimpleName();

	// 每个矩阵坐标个数
	private static final int MATRIX_COORDINATE_COUNT = 16;

	// 模型矩阵：记录当前变换
	private static float[] mMMatrix;
	// 视图矩阵：摄像机位置朝向
	private static float[] mVMatrix = new float[MATRIX_COORDINATE_COUNT];
	// 投影矩阵：正交投影、透视投影
	private static float[] mPMatrix = new float[MATRIX_COORDINATE_COUNT];
	// 总变换矩阵
	private static float[] mMVPMatrix = new float[MATRIX_COORDINATE_COUNT];

	// 矩阵栈：用于保存和恢复矩阵
	private static int nStackTop = -1;
	private static int MAX_MATRIX_NUMBER;
	private static float[][] mStack;

	/**
	 * 初始化模型矩阵
	 */
	public static void initStack(int maxMatrixNumber) {
		MAX_MATRIX_NUMBER = maxMatrixNumber;
		mStack = new float[MAX_MATRIX_NUMBER][MATRIX_COORDINATE_COUNT];

		mMMatrix = new float[MATRIX_COORDINATE_COUNT];
		Matrix.setIdentityM(mMMatrix, 0);
	}

	/**
	 * 保存模型矩阵
	 */
	public static void pushMatrix() {
		if (nStackTop < MAX_MATRIX_NUMBER - 1) {
			nStackTop++;
			for (int i = 0; i < MATRIX_COORDINATE_COUNT; i++) {
				mStack[nStackTop][i] = mMMatrix[i];
			}
		} else {
			LogUtil.LogE(TAG, "pushMatrix error, maxMatrixNumber = " + MAX_MATRIX_NUMBER + ", nStackTop = " + nStackTop);
		}
	}

	/**
	 * 恢复模型矩阵
	 */
	public static void popMatrix() {
		if (nStackTop >= 0) {
			for (int i = 0; i < MATRIX_COORDINATE_COUNT; i++) {
				mMMatrix[i] = mStack[nStackTop][i];
			}
			nStackTop--;
		} else {
			LogUtil.LogE(TAG, "popMatrix error, maxMatrixNumber = " + MAX_MATRIX_NUMBER + ", nStackTop = " + nStackTop);
		}
	}

	/**
	 * 沿xyz轴移动
	 */
	public static void translate(float x, float y, float z) {
		Matrix.translateM(mMMatrix, 0, x, y, z);
	}

	/**
	 * 绕xyz轴转动
	 */
	public static void rotate(float angle, float x, float y, float z) {
		Matrix.rotateM(mMMatrix, 0, angle, x, y, z);
	}

	/**
	 * 沿xyz轴缩放
	 */
	public static void scale(float x, float y, float z) {
		Matrix.scaleM(mMMatrix, 0, x, y, z);
	}

	/**
	 * 设置摄像机位置
	 * 
	 * @param eyeX
	 *            摄像机位置x
	 * @param eyeY
	 *            摄像机位置y
	 * @param eyeZ
	 *            摄像机位置z
	 * @param centerX
	 *            摄像机目标点x
	 * @param centerY
	 *            摄像机目标点y
	 * @param centerZ
	 *            摄像机目标点z
	 * @param upX
	 *            摄像机UP向量x分量
	 * @param upY
	 *            摄像机UP向量y分量
	 * @param upZ
	 *            摄像机UP向量z分量
	 */
	public static void setLookAt(float eyeX, float eyeY, float eyeZ, float centerX, float centerY, float centerZ, float upX, float upY, float upZ) {
		Matrix.setLookAtM(mVMatrix, 0, eyeX, eyeY, eyeZ, centerX, centerY, centerZ, upX, upY, upZ);
	}

	/**
	 * 设置透视投影
	 * 
	 * @param left
	 *            near面的left
	 * @param right
	 *            near面的right
	 * @param bottom
	 *            near面的bottom
	 * @param top
	 *            near面的top
	 * @param near
	 *            near面距离
	 * @param far
	 *            far面距离
	 */
	public static void setProjectFrustum(float left, float right, float bottom, float top, float near, float far) {
		Matrix.frustumM(mPMatrix, 0, left, right, bottom, top, near, far);
	}

	/**
	 * 设置正交投影
	 * 
	 * @param left
	 *            near面的left
	 * @param right
	 *            near面的right
	 * @param bottom
	 *            near面的bottom
	 * @param top
	 *            near面的top
	 * @param near
	 *            near面距离
	 * @param far
	 *            far面距离
	 */
	public static void setProjectOrtho(float left, float right, float bottom, float top, float near, float far) {
		Matrix.orthoM(mPMatrix, 0, left, right, bottom, top, near, far);
	}

	/**
	 * 获取模型矩阵
	 */
	public static float[] getMMatrix() {
		return mMMatrix;
	}

	/**
	 * 获取总变换矩阵
	 */
	public static float[] getMVPMatrix() {
		Matrix.multiplyMM(mMVPMatrix, 0, mVMatrix, 0, mMMatrix, 0);
		Matrix.multiplyMM(mMVPMatrix, 0, mPMatrix, 0, mMVPMatrix, 0);
		return mMVPMatrix;
	}

}
